import cv2
import numpy as np
import matplotlib.pyplot as plt
import pygetwindow as gw
import time

import behavior
import tool

gray = None
grid_poins = None   

col_numbers = []
row_numbers = []

# 寻找窗体并置于上方
def prepare_window():
    try:
        # 窗体参数
        window_title = "每天数独"
        window_width = 791
        window_height = 1430

        # 获取目标窗口
        window = gw.getWindowsWithTitle(window_title)
        if not window:
            print(f"没有找到名为'{window_title}'的窗口")
            return
        
        # 获取窗口对象
        window = window[0]
        
        # 如果窗口被最小化，先恢复它
        if window.isMinimized:
            window.restore()

        # 激活窗口
        window.activate()

        # 调整窗口至默认位置
        window.moveTo(0, 0)
        window.resizeTo(window_width, window_height)

        # 等待窗口调整
        time.sleep(0.5)

        return window
    
    except Exception as e:
        print(f"准备窗口失败: {e}")

def find_board():
    try:
        global gray, grid_poins

        # 截图
        gray, image = tool.capture()

        # 二值化
        _, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)

        # 保存二值化截图
        binary_path = r"Screenshots\screenshot_binary.png"
        cv2.imwrite(binary_path, binary)
        print(f"二值化截图已保存到{binary_path}")

        # 投影：每行、每列黑色像素数量
        horizontal_sum = np.sum(binary, axis=1)  # 每行
        vertical_sum = np.sum(binary, axis=0)    # 每列

        # 找15条横线（行线）
        row_lines = tool.find_lines(horizontal_sum, 16)  # 16条线包住15个格子
        # 找15条竖线（列线）
        col_lines = tool.find_lines(vertical_sum, 16)

        # 画出来看看
        for y in row_lines:
            cv2.line(image, (0, y), (image.shape[1], y), (0, 255, 0), 1)
        for x in col_lines:
            cv2.line(image, (x, 0), (x, image.shape[0]), (0, 255, 0), 1)

        cv2.imwrite("Screenshots/debug_grid_lines.png", image)\
        
        # 计算每个小格中心
        center_points = []
        for i in range(15):
            row = []
            for j in range(15):
                cx = (col_lines[j] + col_lines[j+1]) / 2
                cy = (row_lines[i] + row_lines[i+1]) / 2
                row.append((int(cx), int(cy)))
            center_points.append(row)

        # 打印一下
        # for row in center_points:
        #     print(row)

        grid_poins = center_points
        print(f"已获取棋盘格子坐标：{grid_poins[0][0]}...")

    except Exception as e:
        print(f"寻找棋盘格子失败：{e}")

def find_col_num():
    try:
        global col_numbers

        # 计算格子的一半长度
        half_side = (grid_poins[0][1][0] - grid_poins[0][0][0]) / 2

        for i in range(15):
            # 裁剪单列的数字图像
            x1, y1 = int(grid_poins[0][i][0] - half_side), 0
            x2, y2 = int(grid_poins[0][i][0] + half_side), int(grid_poins[0][0][1] - half_side - 3)
            cropped_img = gray[y1:y2, x1:x2]
            
            # 二值化图片并去除边缘影响
            binary = tool.binary_crop(cropped_img)
            cv2.imwrite(f"debug_image/col_{i}.png", binary)

            # 投影：每行白色像素数量
            horizontal_sum = np.sum(binary, axis=1)  # 每行

            # 裁剪每个数字
            nums_image = []
            last_is_black = 0
            for j in range(len(horizontal_sum) - 1):
                if horizontal_sum[j] < 1 or j == len(horizontal_sum) - 2: # 全行黑色或最后一行
                    if j - last_is_black > 2: # 遍历到了数字尾部
                        nums_image.append(binary[last_is_black : j, :])
                    last_is_black = j
            
            # 识别列数字
            this_col_nums = []
            for j in range(len(nums_image)):
                num = tool.recognize_digits(nums_image[j], f"{i + 1}列 第{j + 1}个数字")
                this_col_nums.append(num)
            col_numbers.append(this_col_nums)
            print(f"识别第{i + 1}列数字为：{this_col_nums}")


    except Exception as e:
        print(f"寻找列数字失败：{e}")

def find_row_num():
    try:
        global row_numbers

        # 计算格子的一半长度
        half_side = (grid_poins[0][1][0] - grid_poins[0][0][0]) / 2

        for i in range(15):
            # 裁剪单行的数字图像
            x1, y1 = 0, int(grid_poins[i][0][1] - half_side)
            x2, y2 = int(grid_poins[0][0][0] - half_side - 3), int(grid_poins[i][0][1] + half_side)
            cropped_img = gray[y1:y2, x1:x2]
            
            # 二值化图片并去除边缘影响
            binary = tool.binary_crop(cropped_img)
            cv2.imwrite(f"debug_image/row_{i}.png", binary)

            # 投影：每列白色像素数量
            vertical_sum = np.sum(binary, axis=0)  # 每列

            # 裁剪每个数字
            nums_image = []
            record = 0
            curt_is_white = False
            prev_is_white = False
            continuous_black = 0
            for j in range(len(vertical_sum) - 1):

                # 更新当前颜色和连续数量状态
                curt_is_white = vertical_sum[j] > 1
                continuous_black = continuous_black + 1 if curt_is_white == False else 0

                # 主裁切逻辑
                if prev_is_white == False and curt_is_white == True and record == 0:    # 上次黑本次白且没有记录时开始记录
                    record = 1
                elif prev_is_white == True and curt_is_white == False and record > 0:  # 上次白本次黑且正在记录时送检
                    start_point = j - record
                    end_point = j
                    temp_img = binary[:, start_point : end_point]

                    # 检测到非1的单独数字 提前结束
                    if tool.recognize_digits(temp_img) > 1:
                        nums_image.append(temp_img)
                        record = 0
                    else:
                        record = record + 1

                elif (continuous_black == 7 or j == len(vertical_sum) - 2) and record > 0:   # 连续x次黑或最后一列且正在记录时停止记录
                    start_point = j - record
                    end_point = j - continuous_black + 1
                    nums_image.append(binary[:, start_point : end_point])
                    record = 0
                    
                elif record >= 1:   # 并非起始点且正在记录时持续记录
                    record = record + 1

                # 为下一帧更新状态
                prev_is_white = curt_is_white

            # 识别列数字
            this_row_nums = []
            for j in range(len(nums_image)):
                # print(f"开始识别{i + 1}行 第{j + 1}个数字")
                num = tool.recognize_digits(nums_image[j], f"{i + 1}行 第{j + 1}个数字")
                this_row_nums.append(num)
            row_numbers.append(this_row_nums)
            print(f"识别第{i + 1}行数字为：{this_row_nums}")
            

    except Exception as e:
        print(f"寻找行数字失败{e}")

#检查数字识别结果
def check_numbers():
    for i in range(len(col_numbers)):
        if tool.get_line_sum(col_numbers[i]) > 15:
            print(f"出现识别错误：第{i + 1}列数字总和大于15 为{col_numbers[i]}")
    for i in range(len(row_numbers)):
        if tool.get_line_sum(row_numbers[i]) > 15:
            print(f"出现识别错误：第{i + 1}行数字总和大于15 为{row_numbers[i]}")


# 用来点击完整的行
def play_entire_single():
    try:
        # 待点击坐标
        pos_array = []

        # 识别完整列
        for i in range(len(col_numbers)):
            if tool.get_line_sum(col_numbers[i]) == 15:
                print(f"第{i + 1}列是完整的")
                curt = 0 # 索引
                for count in col_numbers[i]:
                    for j in range(count):
                        pos_array.append(grid_poins[curt][i])
                        curt = curt + 1
                    curt = curt + 1
        
        # 识别完整行
        for i in range(len(row_numbers)):
            if tool.get_line_sum(row_numbers[i]) == 15:
                print(f"第{i + 1}行是完整的")
                curt = 0 # 索引
                for count in row_numbers[i]:
                    for j in range(count):
                        pos_array.append(grid_poins[i][curt])
                        curt = curt + 1
                    curt = curt + 1

        # 依次点击
        for pos in pos_array:
            tool.mouse_click(pos)

    except Exception as e:
        print(f"完整的行识别出错：{e}")

# 准备窗体
prepare_window()

# 定位棋盘
find_board()
find_col_num()
find_row_num()
check_numbers()

# 满数字行
play_entire_single()

# behavior.behavior_switch_empty()

# 完整行 两头冲 边缘空 单头墙 远边空 